package io.renren.modules.app.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import io.renren.common.exception.RRException;
import io.renren.common.utils.DateUtils;
import io.renren.common.utils.R;
import io.renren.modules.app.config.AlipayConfigs;
import io.renren.modules.app.entity.AlipayNotifyEntity;
import io.renren.modules.app.entity.OrderEntity;
import io.renren.modules.app.service.AgentService;
import io.renren.modules.app.service.AlipayNotifyService;
import io.renren.modules.app.service.OrderService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @Auther zxl
 * @Date 2018/12/19 16:00
 * @Description alipay
 **/
@RequestMapping("/app")
@Controller
public class AlipayController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private OrderService orderService;
    @Autowired
    private AgentService agentService;

    @Autowired
    AlipayNotifyService alipayNotifyService;

    @Autowired
    AlipayConfigs alipayConfigs;

    /**
     *
     * @Title: AlipayController.java
     * @Description: 前往支付宝第三方网关进行支付
     */
    @RequestMapping(value = "/alipay/goAlipay/{orderId}", produces = "text/html; charset=UTF-8")
    public void goAlipay(@PathVariable("orderId") String orderId,
                           HttpServletRequest request, HttpServletResponse response) throws RRException, IOException {
//
//        long userId = (Long)request.getAttribute("userId");

//        logger.info("用户："+userId+"，订单："+orderId+",--------开始支付");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out=response.getWriter();

        logger.info("订单："+orderId+",--------开始支付");

        if(StringUtils.isBlank(orderId)){
            logger.error("orderId无效");
            out.print("<html><head><title>预检车平台</title></head><body>"+
                    "<h1 style=\"color: green;\">无效订单号！</h1>"
                    +"<a href=\"http://jc.zonguo.cn:6060/order_list\" title=\"返回订单页面\" style=\"color: blue;\">返回订单页面</a>"
                    +"</body></html>");
            return;
        }


        OrderEntity orderEntity = orderService.getOneByOrderId(orderId);
        if (orderEntity == null){
            logger.error("订单不存在");
            out.print("<html><head><title>预检车平台</title></head><body>"+
                    "<h1 style=\"color: green;\">订单不存在！</h1>"
                    +"<a href=\"http://jc.zonguo.cn:6060/order_list\" title=\"返回订单页面\" style=\"color: blue;\">返回订单页面</a>"
                    +"</body></html>");
            return;
        }

        AlipayNotifyEntity alipayNotify = alipayNotifyService.getOne(orderId);
        if (alipayNotify != null && alipayNotify.getTradeNo()!=null){
            logger.error("已经支付");
            out.print("<html><head><title>预检车平台</title></head><body>"+
                    "<h1 style=\"color: green;\">您已支付！</h1>"
                    +"<h1 style=\"color: green;\">支付宝交易号："+alipayNotify.getTradeNo()+"</h1>"
                    +"<h1 style=\"color: green;\">交易时间："+
                            DateUtils.format(alipayNotify.getReturnTime(),"yyyy-MM-dd HH:mm:ss") +"</h1>"
                    +"<a href=\"http://jc.zonguo.cn:6060/order_list\" title=\"返回订单页面\" style=\"color: blue;\">返回订单页面</a>"
                    +"</body></html>");
            return;
        }else if (alipayNotify == null){
            // 添加支付记录
            AlipayNotifyEntity alipayNotifyEntity = new AlipayNotifyEntity();
            alipayNotifyEntity.setOrderId(orderId);
            alipayNotifyEntity.setCreateTime(new Date());
            alipayNotifyService.insertOne(alipayNotifyEntity);
            return;
        }

        // 获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfigs.getGatewayUrl(), alipayConfigs.getApp_id(),
                alipayConfigs.getMerchant_private_key(), "json", alipayConfigs.getCharset(),
                alipayConfigs.getAlipay_public_key(), alipayConfigs.getSign_type());

        // 设置请求参数
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        alipayRequest.setReturnUrl(alipayConfigs.getReturn_url());
        alipayRequest.setNotifyUrl(alipayConfigs.getNotify_url());

        // 商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderId;
        // 付款金额，必填
        Double total_amount = orderEntity.getOrderMoney();
        // 订单名称，必填
        String subject = orderEntity.getOrderSubject();

        String body = "道火自然 预检车平台 "+subject+" 共："+total_amount;

        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。
        // 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "1c";

        alipayRequest.setBizContent("{" +
                " \"out_trade_no\":\""+out_trade_no+"\"," +
                " \"total_amount\":\""+total_amount+"\"," +
                " \"subject\":\""+subject+"\"," +
                " \"body\":\""+body+"\"," +
                " \"product_code\":\"CHECK_CAR_SERVICE\"" +
                " }");//填充业务参数body

        // 请求
        String result = null;
        try {
            result = alipayClient.pageExecute(alipayRequest).getBody();
          
        } catch (AlipayApiException e) {
            logger.error("订单："+orderId+",请求失败！");
            out.print("<html><head><title>预检车平台</title></head><body>"+
                    "<h1 style=\"color: green;\">支付失败！</h1>"
                    +"<a href=\"http://jc.zonguo.cn:6060/order_list\" title=\"返回订单页面\" style=\"color: blue;\">返回订单页面</a>"
                    +"</body></html>");
            e.printStackTrace();
            return;
        }
        response.setContentType("text/html;charset=" + alipayConfigs.getCharset());
        try {
            response.getWriter().write(result);//直接将完整的表单html输出到页面
            response.getWriter().flush();
            response.getWriter().close();
        } catch (IOException e) {
            logger.error("IO异常",e);
            e.printStackTrace();
        }

    }

    /**
     * 支付宝页面跳转同步通知页面
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/alipay/alipayReturnNotice")
    @ResponseBody
    public void alipayReturnNotice(HttpServletRequest request, HttpServletResponse response) throws Exception {

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out=response.getWriter();

        System.out.println("支付成功, 进入同步通知接口...");

        // 获取支付宝GET过来反馈信息s
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfigs.getAlipay_public_key(),
                alipayConfigs.getCharset(), alipayConfigs.getSign_type()); // 调用SDK验证签名

        // ——请在这里编写您的程序（以下代码仅作参考）——
        if (signVerified) {

            /**
             * 本商家的订单号
             */
            String out_trade_no = new String(request.getParameter("out_trade_no")
                    .getBytes("ISO-8859-1"), "UTF-8");

            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no")
                    .getBytes("ISO-8859-1"), "UTF-8");

            // 付款金额
            String total_amount = new String(request.getParameter("total_amount")
                    .getBytes("ISO-8859-1"), "UTF-8");

            System.out.println("商户订单号："+out_trade_no);
            System.out.println("支付宝交易号:"+trade_no);
            System.out.println("付款金额:"+total_amount);

            AlipayNotifyEntity alipayNotifyEntity = new AlipayNotifyEntity();
            alipayNotifyEntity.setOrderId(out_trade_no);
            alipayNotifyEntity.setTradeNo(trade_no);
            alipayNotifyEntity.setTotalAmount(Double.parseDouble(total_amount));
            alipayNotifyEntity.setReturnTime(new Date());
            alipayNotifyService.alipayReturn(alipayNotifyEntity);

            OrderEntity orderEntity = orderService.getOneByOrderId(out_trade_no);

            out.print("<html><head><title>预检车平台</title></head><body>"+
                    "<h1 style=\"color: green;\">支付成功！</h1>"
                    +"<table>"
                    +"<tr><td>订单编号："+out_trade_no+"</tr>"
                    +"<tr><td>支付宝交易号："+trade_no+"</tr>"
                    +"<tr><td>实付金额："+total_amount+"</tr>"
                    +"<tr><td>购买商品："+orderEntity.getOrderSubject()+"</tr>"
                    +"</table>"
                    +"<a href=\"http://jc.zonguo.cn:6060/order_list\" title=\"返回订单页面\" style=\"color: blue;\">返回订单页面</a>"
                    +"</body></html>");
            return;

        }
        out.print("<html><head><title>预检车平台</title></head><body>"
                +"<h1>支付验签失败...</h1>"
                +"</body></html>");
        logger.error("同步通知，支付验签失败...");

    }

    /**
     * 异步通知
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/alipay/alipayNotifyNotice")
    @ResponseBody
    public String alipayNotifyNotice(HttpServletRequest request, HttpServletRequest response) throws Exception {

        System.out.println("支付成功, 进入异步通知接口...");

        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfigs.getAlipay_public_key(),
                alipayConfigs.getCharset(), alipayConfigs.getSign_type()); // 调用SDK验证签名

        // ——请在这里编写您的程序（以下代码仅作参考）——

        /*
         * 实际验证过程建议商户务必添加以下校验： 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
         * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）， 3、校验通知中的seller_id（或者seller_email)
         * 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
         * 4、验证app_id是否为该商户本身。
         */
        if (signVerified) {// 验证成功
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no")
                    .getBytes("ISO-8859-1"), "UTF-8");

            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no")
                    .getBytes("ISO-8859-1"), "UTF-8");

            // 交易状态
            String trade_status = new String(request.getParameter("trade_status")
                    .getBytes("ISO-8859-1"), "UTF-8");

            // 付款金额
            String buyer_pay_amount = new String(request.getParameter("buyer_pay_amount")
                    .getBytes("ISO-8859-1"), "UTF-8");

            // 买家支付宝账号
            String buyer_logon_id = new String(request.getParameter("buyer_logon_id")
                    .getBytes("ISO-8859-1"), "UTF-8");

            AlipayNotifyEntity alipayNotifyEntity = new AlipayNotifyEntity();
            alipayNotifyEntity.setOrderId(out_trade_no);
            alipayNotifyEntity.setTradeNo(trade_no);
            alipayNotifyEntity.setTradeStatus(trade_status);
            alipayNotifyEntity.setBuyerLogonId(buyer_logon_id);
            alipayNotifyEntity.setBuyerPayAmount(Double.parseDouble(buyer_pay_amount));
            alipayNotifyEntity.setNotifyTime(new Date());
            alipayNotifyService.alipayNotify(alipayNotifyEntity);
            logger.info("订单："+out_trade_no+",支付成功");
            return "success";

        } else {// 验证失败
            logger.error("异步通知，支付验签失败...");
            return "failure";
        }
    }

}
